<template>
<div :class="$style.container">
  <img :src="avatar" :class="$style.avatar" @click.stop="handleAvatarClick"/>
  <input type="file" @change="handleInputChange" :class="$style.upload" id="file" name="image" accept="image/*"/>
</div>
</template>

<script>
export default {
  data () {
    return {
      imgFile: {}
    }
  },
  created () {

  },
  computed: {
    avatar () {
      let img = this.$prefix + 'downLoadFile?fileId=' + this.$store.getters.user.avatar
      return img
    }
  },
  methods: {
    handleAvatarClick () {
      document.getElementById('file').click()
    },
    handleInputChange (event) {
      // 获取当前选中的文件
      const file = event.target.files[0]
      const imgMasSize = 1024 * 1024 * 10 // 10MB

      // 检查文件类型
      if (['jpeg', 'png', 'gif', 'jpg'].indexOf(file.type.split('/')[1]) < 0) {
        // 自定义报错方式
        // Toast.error("文件类型仅支持 jpeg/png/gif！", 2000, undefined, false);
        this.$emit('error', '文件类型仅支持 jpeg/png/gif！')
        return
      }

      // 文件大小限制
      if (file.size > imgMasSize) {
        // 文件大小自定义限制
        // Toast.error("文件大小不能超过10MB！", 2000, undefined, false);
        this.$emit('error', '文件大小不能超过10MB！')
        return
      }

      // 判断是否是ios
      if (window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)) {
        // iOS
        this.transformFileToFormData(file)
        return
      }

     // 图片压缩之旅
      this.transformFileToDataUrl(file)
    },
    // 将File append进 FormData
    transformFileToFormData (file) {
      const formData = new FormData()
      // 自定义formData中的内容
      // type
      formData.append('type', file.type)
      // size
      formData.append('size', file.size || 'image/jpeg')
      // name
      formData.append('name', file.name)
      // lastModifiedDate
      formData.append('lastModifiedDate', file.lastModifiedDate)
      // append 文件
      formData.append('files', file)
      // 上传图片
      this.uploadImg(formData)
    },
    // 将file转成dataUrl
    transformFileToDataUrl (file) {
      const imgCompassMaxSize = 200 * 1024 // 超过 200k 就压缩

      // 存储文件相关信息
      this.imgFile.type = file.type || 'image/jpeg' // 部分安卓出现获取不到type的情况
      this.imgFile.size = file.size
      this.imgFile.name = file.name
      this.imgFile.lastModifiedDate = file.lastModifiedDate

      // 封装好的函数
      const reader = new FileReader()

      // file转dataUrl是个异步函数，要将代码写在回调里
      reader.onload = function (e) {
        const result = e.target.result

        if (result.length < imgCompassMaxSize) {
          this.compress(result, this.processData, false)    // 图片不压缩
        } else {
          this.compress(result, this.processData)            // 图片压缩
        }
      }

      reader.readAsDataURL(file)
    },
    // 使用canvas绘制图片并压缩
    compress (dataURL, callback, shouldCompress = true) {
      const img = new window.Image()

      img.src = dataURL

      img.onload = function () {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')

        canvas.width = img.width
        canvas.height = img.height

        ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

        let compressedDataUrl

        if (shouldCompress) {
          compressedDataUrl = canvas.toDataURL(this.imgFile.type, 0.2)
        } else {
          compressedDataUrl = canvas.toDataURL(this.imgFile.type, 1)
        }

        callback(compressedDataUrl)
      }
    },

    processData (dataURL) {
      // 这里使用二进制方式处理dataUrl
      const binaryString = window.atob(this.dataUrl.split(',')[1])
      const arrayBuffer = new ArrayBuffer(binaryString.length)
      const intArray = new Uint8Array(arrayBuffer)
      const imgFile = this.imgFile

      for (let i = 0, j = binaryString.length; i < j; i++) {
        intArray[i] = binaryString.charCodeAt(i)
      }

      const data = [intArray]

      let blob

      try {
        blob = new Blob(data, { type: imgFile.type })
      } catch (error) {
        window.BlobBuilder = window.BlobBuilder ||
            window.WebKitBlobBuilder ||
            window.MozBlobBuilder ||
            window.MSBlobBuilder
        if (error.name === 'TypeError' && window.BlobBuilder) {
          const builder = new BlobBuilder()
          builder.append(arrayBuffer)
          blob = builder.getBlob(imgFile.type)
        } else {
            // Toast.error("版本过低，不支持上传图片", 2000, undefined, false);
          this.$emit('error', '版本过低，不支持上传图片')
          // throw new Error('版本过低，不支持上传图片')
        }
      }

      // blob 转file
      const fileOfBlob = new File([blob], imgFile.name)
      const formData = new FormData()

      // type
      formData.append('type', imgFile.type)
      // size
      formData.append('size', fileOfBlob.size)
      // name
      formData.append('name', imgFile.name)
      // lastModifiedDate
      formData.append('lastModifiedDate', imgFile.lastModifiedDate)
      // append 文件
      formData.append('file', fileOfBlob)

      this.uploadImg(formData)
    },

    // 上传图片
    uploadImg (formData) {
      let that = this
      const xhr = new XMLHttpRequest()

      // 进度监听
      xhr.upload.addEventListener('progress', (e) => { console.log(e.loaded / e.total) }, false)
      // 加载监听
      // xhr.addEventListener('load', ()=>{console.log("加载中");}, false);
      // 错误监听
      xhr.addEventListener('error', () => {
        that.$emit('error', '上传失败！')
      }, false)
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          const result = JSON.parse(xhr.responseText)

          if (result.code === 0) {
            // 上传成功

            that.$store.commit('SET_USER', {avatar: result.data[0]._id})
            that.$emit('uploadSuccess', result.data[0]._id)
          } else {
            // 上传失败
            that.$emit('error', '上传失败！')
          }
        }
      }
      xhr.open('POST', `${this.$prefix}uploadFile`, true)
      xhr.send(formData)
    }
  }
}
</script>

<style lang='less' module>
.container {
   text-align: center;
   padding-top: 50px;
   box-sizing: border-box;
  .avatar {
    width: 100px;
    height:100px;
    object-fit: cover;
    border-radius: 10px;
    background: #e36049;
  }
  .upload {
    display: none;
  }
}

</style>